import { provide } from 'vue';
import providedb from './providedb';
import providedbwork from './providedbwork';
import provideglobal from './provideglobal';
import providews from './providews';
import providefn from './providefn';

// 仅执行一次
export default (opt: any) => {
    const { AsaiJsAs } = opt;
    // 把模型上的数据挂载到vue上，全局可用
    const WD: any = window as any;

    Object.assign(providefn.providefn.data, { ...AsaiJsAs, ...opt });

    const $ujtasai: any = {
        $db: providedb.providedb.data,
        $dbwork: providedbwork.providedbwork.data,
        $ws: providews.providews.data,
        $global: provideglobal.provideglobal.data,
        $model: WD.$GYS.$webmodel,
        $fn: providefn.providefn.data,
    };

    WD.$GYS.ujt = $ujtasai;

    // 控制台打印
    $ujtasai.$fn.lo = (...args: any) => {
        if ($ujtasai.$global.sys?.onconsole) {
            if (!args?.[0]) {
                $ujtasai.$model.gysfn.log();
            } else if (args.length > 0) {
                let nstyle: string = '';
                let nstring: string = '';
                let narr: string = '';
                if (args[1] && typeof args[1] === 'string') {
                    const [ntype, nstringarg, ...argarr] = args;
                    nstring = nstringarg;
                    narr = argarr;
                    if (Array.isArray(args[0]) && args[0].length === 2) {
                        nstyle = logStyle(args[0][0], args[0][1], '12px');
                    } else if (typeof args[0] === 'number') {
                        nstyle = logStyleMk(ntype, 12);
                    }
                }
                if (nstyle) {
                    console.log('%c' + nstring, nstyle, ...narr);
                } else {
                    console.log(...args);
                }
            }
        }
    };

    // 控制台打印平台模块数据
    $ujtasai.$model.gysfn.log = () => {
        console.log(
            '%c$fn',
            logStyleMk(6, 18),
            sizeof($ujtasai.$fn),
            $ujtasai.$fn
        );
        console.log(
            '%c$model',
            logStyleMk(5, 18),
            sizeof($ujtasai.$model),
            $ujtasai.$model
        );
        console.log(
            '%c$global',
            logStyleMk(4, 18),
            sizeof($ujtasai.$global),
            $ujtasai.$global
        );
        console.log(
            '%c$ws',
            logStyleMk(3, 18),
            sizeof($ujtasai.$ws),
            $ujtasai.$ws
        );
        console.log(
            '%c$db',
            logStyleMk(2, 18),
            sizeof($ujtasai.$db),
            $ujtasai.$db
        );
        console.log(
            '%c$dbwork',
            logStyleMk(1, 18),
            sizeof($ujtasai.$dbwork),
            $ujtasai.$dbwork
        );

        return 'Web Model Log。';
    };
    function logStyleMk(ntype: number, nfs: number = 18) {
        let nstyle = '';
        if (ntype === 1) {
            nstyle = logStyle('black', 'pink', nfs + 'px');
        } else if (ntype === 2) {
            nstyle = logStyle('black', 'cyan', nfs + 'px');
        } else if (ntype === 3) {
            nstyle = logStyle('black', 'yellow', nfs + 'px');
        } else if (ntype === 4) {
            nstyle = logStyle('white', 'blue', nfs + 'px');
        } else if (ntype === 5) {
            nstyle = logStyle('white', 'red', nfs + 'px');
        } else if (ntype === 6) {
            nstyle = logStyle('white', 'green', nfs + 'px');
        }
        return nstyle;
    }
    // 控制台打印样式封装函数
    function logStyle(
        color: string,
        bgcolor: string,
        fontsize: string = '18px'
    ) {
        return (
            'font-size:' +
            fontsize +
            ';font-weight:bold;border-radius:20px;padding:0 10px;color:' +
            color +
            ';background-color:' +
            bgcolor +
            ';'
        );
    }
    // 获取指定模块obj数据的大小
    function sizeof(obj: any) {
        try {
            return (
                'size=>' +
                ((obj && JSON.stringify(obj)?.length) / 1024).toFixed(3) +
                'KB'
            );
        } catch (e) {
            return '';
        }
    }

    // 获取webmodel模型by url
    const { fetchPublic } = $ujtasai.$fn.AsaiModel('./webmodel/');
    $ujtasai.$fn.initmodel = fetchPublic;

    $ujtasai.$fn.startLink = () => {
        return new Promise((resolve: any, reject: any) => {
            $ujtasai.$fn
                .initmodel('sys/server.json')
                .then((res: any) => {
                    const linkData: any = { api: {}, ws: {} };
                    ['api', 'ws'].forEach((type: string) => {
                        Object.keys(res?.[type] || {}).forEach((key: any) => {
                            if (key != 'default') {
                                linkData[type][key] = {
                                    ...res[type][key],
                                    url: $ujtasai.$fn.As.getUrlByCfg(
                                        res[type][key],
                                        type == 'ws' ? 1 : 0
                                    ),
                                };
                            }
                        });
                    });
                    $ujtasai.$fn.As.localSet(
                        'as-link',
                        JSON.stringify(linkData)
                    );
                    $ujtasai.$global.link = linkData;
                    resolve($ujtasai.$global.link);
                })
                .catch((err: any) => {
                    reject(err);
                });
        });
    };
    $ujtasai.$fn.saveLink = (data: any) => {
        $ujtasai.$global.link = data;
        $ujtasai.$fn.As.localSet(
            'as-link',
            JSON.stringify($ujtasai.$global.link)
        );
    };
    $ujtasai.$fn.initLink = (type: number = 0) => {
        return new Promise((resolve: any, reject: any) => {
            if (type) {
                $ujtasai.$fn
                    .startLink()
                    .then((res: any) => {
                        resolve(res);
                    })
                    .catch((err: any) => {
                        reject(err);
                    });
            } else {
                let aslink = $ujtasai.$fn.As.localGet('as-link');
                if (aslink) {
                    // 使用缓存中的连接属性
                    $ujtasai.$global.link = JSON.parse(aslink);
                    if (
                        $ujtasai.$global.link?.api &&
                        $ujtasai.$global.link?.ws
                    ) {
                        resolve($ujtasai.$global.link);
                    } else {
                        $ujtasai.$fn
                            .startLink()
                            .then((res: any) => {
                                resolve(res);
                            })
                            .catch((err: any) => {
                                reject(err);
                            });
                    }
                } else {
                    $ujtasai.$fn
                        .startLink()
                        .then((res: any) => {
                            resolve(res);
                        })
                        .catch((err: any) => {
                            reject(err);
                        });
                }
            }
        });
    };
    // 缓存路径解析结果（使用 WeakMap 减少内存泄漏风险）
    const pathCache = new Map<string, string[]>();
    // 参数替换正则预编译（提升替换性能）
    const placeholderRegex = /\$(\d+)/g;
    $ujtasai.$fn.lg = (path: string, params?: string | string[]) => {
        if (typeof path !== 'string' || !path) {
            return;
        }
        // 1. 路径解析 + 缓存
        let keys = pathCache.get(path);
        if (!keys) {
            keys = path.split('.');
            pathCache.set(path, keys);
        }
        // 2. 获取语言文本（添加安全断言）
        const rawText = keys.reduce(
            (acc: any, key) => acc?.[key as keyof typeof acc],
            $ujtasai.$global.lang
        );
        // 3. 参数替换逻辑优化
        if (!params || params.length === 0) return rawText;
        // 统一参数格式（字符串转数组）
        const paramsArray = Array.isArray(params) ? params : [params];
        // 单次正则替换完成所有参数注入
        const replacedText = rawText.replace(
            placeholderRegex,
            (match: any, indexStr: any) => {
                const index = parseInt(indexStr, 10) - 1;
                return paramsArray[index] ?? match; // 找不到参数时保留原占位符
            }
        );
        return replacedText;
    };
    $ujtasai.$fn.changetheme = (themety: string = '') => {
        return new Promise((resolve: any, reject: any) => {
            try {
                let curtheme: string = '';
                if ($ujtasai.$global?.sys?.local?.theme) {
                    curtheme =
                        $ujtasai.$fn.As.localGet(
                            $ujtasai.$global?.sys?.local?.theme
                        ) ||
                        $ujtasai.$model.data.sys.settingtheme.theme ||
                        $ujtasai.$model.data.sys.configdata.theme[0];
                } else {
                    curtheme =
                        $ujtasai.$model.data.sys.settingtheme.theme ||
                        $ujtasai.$model.data.sys.configdata.theme[0];
                }
                if (themety && curtheme === themety) {
                    resolve();
                } else {
                    if (themety === 'auto') {
                        curtheme =
                            curtheme ==
                            $ujtasai.$model.data.sys.configdata.theme[0]
                                ? $ujtasai.$model.data.sys.configdata.theme[1]
                                : $ujtasai.$model.data.sys.configdata.theme[0];
                    } else if (themety) {
                        curtheme = themety;
                    }
                    if ($ujtasai.$global?.sys?.local?.theme) {
                        $ujtasai.$fn.As.localSet(
                            $ujtasai.$global?.sys?.local?.theme,
                            curtheme
                        );
                    }
                }
                // console.log(666.10022, curtheme);
                if (curtheme && $ujtasai.$global?.config?.theme !== curtheme) {
                    if (
                        $ujtasai.$global?.config?.theme &&
                        document?.body?.classList?.contains(
                            $ujtasai.$global.config.theme
                        )
                    ) {
                        document.body.classList.remove(
                            $ujtasai.$global.config.theme
                        );
                    }
                    $ujtasai.$global.config.theme = curtheme;
                }
                if (!document?.body?.classList?.contains(curtheme)) {
                    document.body.classList.add(curtheme);
                }
                resolve();
            } catch (e) {
                reject(e);
            }
        });
    };
    // 初始化国际化语言
    $ujtasai.$fn.initlang = (langty: string = '') => {
        let curLangTy: string = '';
        if ($ujtasai.$global?.sys?.local?.lang) {
            curLangTy =
                langty ||
                $ujtasai.$fn.As.localGet($ujtasai.$global?.sys?.local?.lang) ||
                $ujtasai.$model.data.sys.settinglang.lang ||
                $ujtasai.$model.data.sys.configdata.lang[0];
        } else {
            curLangTy =
                langty ||
                $ujtasai.$model.data.sys.settinglang.lang ||
                $ujtasai.$model.data.sys.configdata.lang[0];
        }
        if (!$ujtasai.$global?.lang) {
            $ujtasai.$global.lang = {};
        }
        return new Promise((resolve: any, reject: any) => {
            $ujtasai.$fn
                .initmodel('lang/dirlang.json', curLangTy + '/')
                .then((res: any) => {
                    Object.assign($ujtasai.$global.lang, res);
                    resolve($ujtasai.$global.lang);
                })
                .catch((err: any) => {
                    reject(err);
                });
        });
    };
    $ujtasai.$fn.changelang = (langty: string = '') => {
        let curLangTy: string = '';
        if ($ujtasai.$global?.sys?.local?.lang) {
            curLangTy =
                $ujtasai.$fn.As.localGet($ujtasai.$global?.sys?.local?.lang) ||
                $ujtasai.$model.data.sys.settinglang.lang ||
                $ujtasai.$model.data.sys.configdata.lang[0];
        } else {
            curLangTy =
                $ujtasai.$global.config.langcur ||
                $ujtasai.$model.data.sys.settinglang.lang ||
                $ujtasai.$model.data.sys.configdata.lang[0];
        }
        return new Promise((resolve: any, reject: any) => {
            if (langty && curLangTy === langty && $ujtasai.$global?.lang) {
                resolve(curLangTy);
            } else {
                if (langty === 'auto') {
                    curLangTy =
                        curLangTy == $ujtasai.$model.data.sys.configdata.lang[0]
                            ? $ujtasai.$model.data.sys.configdata.lang[1]
                            : $ujtasai.$model.data.sys.configdata.lang[0];
                } else if (langty) {
                    curLangTy = langty;
                }
                if ($ujtasai.$global?.sys?.local?.lang) {
                    $ujtasai.$fn.As.localSet(
                        $ujtasai.$global?.sys?.local?.lang,
                        curLangTy
                    );
                }
                // $ujtasai.$model.data.sys.settinglang.lang = curLangTy; // 即时性更改语言包
                // $ujtasai.$global.config.lang = curLangTy;
                if (
                    $ujtasai.$global?.sys?.local?.lang ||
                    !$ujtasai.$global.config.lang
                ) {
                    $ujtasai.$global.config.lang = curLangTy;
                    $ujtasai.$fn
                        .initlang(curLangTy)
                        .then((_res: any) => {
                            resolve(curLangTy);
                        })
                        .catch((err: any) => {
                            reject(err);
                        });
                } else {
                    resolve(curLangTy);
                }
            }
        });
    };
    // 初始化webmodel模型
    $ujtasai.$fn.initweb = async (insProxy: any) => {
        try {
            // 挂载引擎文件到到$fn上
            Object.assign($ujtasai.$fn, insProxy.$engineasai || {});
            Object.assign($ujtasai.$fn, insProxy.$engineasailib || {});

            // 初始化系统配置
            $ujtasai.$model.data.asai = await $ujtasai.$fn.initmodel(
                'asai/dirmodel.json'
            );
            const resasai: any = await $ujtasai.$fn.initmodel(
                'asai/dirglobal.json'
            );
            $ujtasai.$global.asai = {};
            Object.keys(resasai).forEach((key: string) => {
                Object.assign($ujtasai.$global.asai, resasai[key]);
            });
            $ujtasai.$model.data.sys = await $ujtasai.$fn.initmodel(
                'sys/dirmodel.json'
            );
            const ressys: any = await $ujtasai.$fn.initmodel(
                'sys/dirglobal.json'
            );
            $ujtasai.$global.sys = {};
            Object.keys(ressys).forEach((key: string) => {
                Object.assign($ujtasai.$global.sys, ressys[key]);
            });

            // 路由处理
            if ($ujtasai.$model.data.sys.configrouter) {
                $ujtasai.$global.sys.router =
                    $ujtasai.$model.data.sys.configrouter;
                for (
                    let i = 0;
                    i < $ujtasai.$global.sys.router.config.models.length;
                    i++
                ) {
                    const resrouter: any = await $ujtasai.$fn.initmodel(
                        $ujtasai.$global.sys.router.config.models[i] +
                            '/configrouter.json'
                    );
                    if (typeof resrouter == 'object') {
                        // 这里单独处理router配置:将子模块中的router引入到这里来
                        Object.entries(resrouter).forEach(
                            ([key, value]: any) => {
                                if (key === 'rights') {
                                    Object.entries(value).forEach(
                                        ([keyc, valuec]: any) => {
                                            if (valuec) {
                                                $ujtasai.$global.sys.router.rights[
                                                    keyc
                                                ].push(...valuec);
                                            }
                                        }
                                    );
                                } else {
                                    Object.assign(
                                        $ujtasai.$global.sys.router[key],
                                        value
                                    );
                                }
                            }
                        );
                    }
                }
            }

            $ujtasai.$fn.lo(); // 打印VUE中全局可用公共模型
            // 开启LINK服务
            await $ujtasai.$fn.initLink();
            // 初始化主题
            await $ujtasai.$fn.changetheme();
            fnInit();

            function fnInit() {
                // 前置处理部分
                const { protocol, hostname, port, hash } = WD.location;
                $ujtasai.$global.location = {
                    protocol,
                    hostname,
                    port,
                    hash: hash.replace('#', ''),
                    comps: [],
                    query: {},
                };
                $ujtasai.$fn.AsRouter.initHash($ujtasai.$global.location);
                freshHash();
                function freshHash() {
                    $ujtasai.$fn.AsRouter.setRouter($ujtasai.$global.location);
                }
                $ujtasai.$fn.setquery = (value: any = {}, type: number = 0) => {
                    let tmpStr: string;
                    if (type) {
                        tmpStr = new URLSearchParams({
                            ...($ujtasai.$global.location.query || {}),
                            ...(value || {}),
                        }).toString();
                    } else {
                        tmpStr = new URLSearchParams(value || {}).toString();
                    }
                    if (tmpStr) {
                        tmpStr =
                            $ujtasai.$global.location.hash.split('?')[0] +
                            '?' +
                            tmpStr;
                    } else {
                        tmpStr = $ujtasai.$global.location.hash.split('?')[0];
                    }
                    $ujtasai.$fn.AsRouter.setHash(
                        $ujtasai.$global.location,
                        tmpStr
                    );
                    freshHash();
                };
                $ujtasai.$fn.sethash = (value: string = '') => {
                    $ujtasai.$fn.AsRouter.setHash(
                        $ujtasai.$global.location,
                        value
                    );
                    // freshHash();
                };
                $ujtasai.$fn.exit = (type: any = 0) => {
                    $ujtasai.$fn.As.localSet('as-user-info', '');
                    $ujtasai.$global.user.info = null;
                    $ujtasai.$global.code.token = null;
                    if (type) {
                        $ujtasai.$fn.sethash('');
                        $ujtasai.$fn.As.localReload();
                    }
                };
                $ujtasai.$fn.login = () => {
                    $ujtasai.$fn.As.localSet('as-user-info', '');
                    $ujtasai.$global.user.info = null;
                    $ujtasai.$fn.sethash(
                        $ujtasai.$global.sys?.router?.config?.login ||
                            'user/login'
                    );
                };
            }
        } catch (err) {
            console.error(666.003, err);
        }
    };

    // 初始化webmodel模型
    $ujtasai.$fn.initrouter = () => {
        if (
            $ujtasai.$global?.sys?.devlevel &&
            !$ujtasai.$global.url[$ujtasai.$global.module.value]
        ) {
            const regex = /^\.\/(.*?)\/default\.vue$/;
            $ujtasai.$global.url[$ujtasai.$global.module.value] = [
                ...Object.keys($ujtasai.$model.comps)
                    ?.map((el: string) => {
                        // console.log(
                        //     666.002,
                        //     el.match(regex),
                        //     regex.test(el),
                        //     el
                        // );
                        if (regex.test(el)) {
                            const match = el.match(regex);
                            if (match) {
                                return match[1];
                            }
                        }
                        return '';
                    })
                    .filter((elf: string) => elf),
            ].map((el: any) => {
                return {
                    value: el,
                    label: el,
                    // label: el.slice(el.lastIndexOf('/') + 1),
                };
            });
            $ujtasai.$global.url[$ujtasai.$global.module.value].push(
                ...Object.keys($ujtasai.$model.appmodules.indexRouters).map(
                    (el: any) => {
                        return {
                            value: el,
                            label: el,
                            type: 'module',
                        };
                    }
                )
            );
        }
    };

    // 从这里提供数据
    provide('$ujtasai', $ujtasai);

    return {
        ...$ujtasai,
        $ujtasai,
    };
};
